from tensorflow import keras
from tensorflow.keras import layers
from keras.callbacks import ModelCheckpoint
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import seaborn as sns
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
import os, shutil, pathlib
train_dir = pathlib.Path("data/train")
new_base_dir = pathlib.Path("datacats_and_dogs_small")
def make_subset(subset_name, start_index, end_index):
for category in ("cat", "dog"):
dir = new_base_dir / subset_name / category
os.makedirs(dir)
fnames = [f"{category}.{i}.jpg" for i in range(start_index, end_index)]
for fname in fnames:
shutil.copyfile(src=train_dir / fname,
dst=dir / fname)
make_subset("train", start_index=0, end_index=1000)
make_subset("validation", start_index=1000, end_index=1500)
make_subset("test", start_index=1500, end_index=2500)
from tensorflow.keras.utils import image_dataset_from_directory
data_folder = pathlib.Path('datacats_and_dogs_small')
train_dataset = image_dataset_from_directory(
data_folder / "train",
image_size=(180, 180),
batch_size=32)
validation_dataset = image_dataset_from_directory(
data_folder / "validation",
image_size=(180, 180),
batch_size=32)
test_dataset = image_dataset_from_directory(
data_folder / "test",
image_size=(180, 180),
batch_size=32)
Found 2000 files belonging to 2 classes. Found 1000 files belonging to 2 classes. Found 2000 files belonging to 2 classes.
type(train_dataset)
tensorflow.python.data.ops.batch_op._BatchDataset
for data_batch, labels_batch in train_dataset:
print("data batch shape:", data_batch.shape)
print("labels batch shape:", labels_batch.shape)
break
data batch shape: (32, 180, 180, 3) labels batch shape: (32,)
import matplotlib.pyplot as plt
plt.imshow(data_batch[0].numpy().astype("uint8"))
<matplotlib.image.AxesImage at 0x2e527db6c50>
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
cols = 5
rows = 2
fig = plt.figure(figsize=(4 * cols - 1, 4.5 * rows - 1))
for i in range(1, 11):
img_path = f'datacats_and_dogs_small/train/cat/cat.{i}.jpg'
img = mpimg.imread(img_path)
ax = fig.add_subplot(rows, cols, i)
ax.imshow(img)
ax.set_title(f'Cat {i}')
ax.axis('off')
fig.suptitle('First 10 Cat Images', fontsize=16)
plt.tight_layout()
plt.show()
plt.close()
fig = plt.figure(figsize=(4 * cols - 1, 4.5 * rows - 1))
for i in range(1, 11):
img_path = f'datacats_and_dogs_small/train/dog/dog.{i}.jpg'
img = mpimg.imread(img_path)
ax = fig.add_subplot(rows, cols, i)
ax.imshow(img)
ax.set_title(f'Cat {i}')
ax.axis('off')
fig.suptitle('First 10 Dog Images', fontsize=16)
plt.tight_layout()
plt.show()
plt.close()
total_cats = len(os.listdir('datacats_and_dogs_small/train/cat'))
total_dogs = len(os.listdir('datacats_and_dogs_small/train/dog'))
pd.DataFrame({'category': ['cat', 'dog'], 'count': [total_cats, total_dogs]}).plot.bar(x='category', y='count', legend=False)
<Axes: xlabel='category'>
# function to get image dimensions
def get_image_dimensions(folder_path):
image_dimensions = []
for filename in os.listdir(folder_path):
if filename.endswith('.jpg') or filename.endswith('.jpg'):
image_path = os.path.join(folder_path, filename)
img = mpimg.imread(image_path)
if img is not None:
height, width, _ = img.shape
image_dimensions.append((filename, width, height))
return image_dimensions
cat_folder_path = 'datacats_and_dogs_small/train/cat'
dog_folder_path = 'datacats_and_dogs_small/train/dog'
# tuples with dimensions of images
cat_dimensions = get_image_dimensions(cat_folder_path)
dog_dimensions = get_image_dimensions(dog_folder_path)
# Convert the list of tuples to a DataFrame
cat_df = pd.DataFrame(cat_dimensions, columns=['filename', 'width', 'height'])
dog_df = pd.DataFrame(dog_dimensions, columns=['filename', 'width', 'height'])
combined_height_df = pd.concat([
cat_df[['height']].assign(image_type='cat'),
dog_df[['height']].assign(image_type='dog')
])
fig = plt.figure(figsize=(12, 6))
sns.displot(data=combined_height_df, x='height', hue='image_type', kde=True,col='image_type', palette='viridis',legend=False)
plt.suptitle('Distribution of Heights of Cat and Dog Images', x=0.5, y=1.05, ha='center', fontsize=16)
plt.show()
<Figure size 1200x600 with 0 Axes>
combined_width_df = pd.concat([
cat_df[['width']].assign(image_type='cat'),
dog_df[['width']].assign(image_type='dog')
])
fig = plt.figure(figsize=(12, 6))
sns.displot(data=combined_width_df, x='width', hue='image_type', kde=True,col='image_type',legend=False)
plt.suptitle('Distribution of Widths of Cat and Dog Images', x=0.5, y=1.05, ha='center', fontsize=16)
plt.show()
<Figure size 1200x600 with 0 Axes>
inputs = keras.Input(shape=(180, 180, 3))
x = layers.Rescaling(1./255)(inputs)
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model_1 = keras.Model(inputs=inputs, outputs=outputs)
model_1.summary()
Model: "model_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_5 (InputLayer) [(None, 180, 180, 3)] 0
rescaling_1 (Rescaling) (None, 180, 180, 3) 0
conv2d_5 (Conv2D) (None, 178, 178, 32) 896
max_pooling2d_4 (MaxPooling (None, 89, 89, 32) 0
2D)
conv2d_6 (Conv2D) (None, 87, 87, 64) 18496
max_pooling2d_5 (MaxPooling (None, 43, 43, 64) 0
2D)
conv2d_7 (Conv2D) (None, 41, 41, 128) 73856
max_pooling2d_6 (MaxPooling (None, 20, 20, 128) 0
2D)
conv2d_8 (Conv2D) (None, 18, 18, 256) 295168
max_pooling2d_7 (MaxPooling (None, 9, 9, 256) 0
2D)
conv2d_9 (Conv2D) (None, 7, 7, 256) 590080
flatten_3 (Flatten) (None, 12544) 0
dense_5 (Dense) (None, 1) 12545
=================================================================
Total params: 991,041
Trainable params: 991,041
Non-trainable params: 0
_________________________________________________________________
model_1.compile(loss="binary_crossentropy",
optimizer="rmsprop",
metrics=["accuracy"])
checkpoint_filepath = 'best_model_model1.hdf5'
callbacks = [
keras.callbacks.ModelCheckpoint(
filepath=checkpoint_filepath,
save_best_only=True,
monitor="val_loss",
mode='min')
]
history_1 = model_1.fit(
train_dataset,
epochs=30,
validation_data=validation_dataset,
callbacks=callbacks)
Epoch 1/30 63/63 [==============================] - 63s 994ms/step - loss: 0.1084 - accuracy: 0.9665 - val_loss: 1.1867 - val_accuracy: 0.7340 Epoch 2/30 63/63 [==============================] - 66s 1s/step - loss: 0.0711 - accuracy: 0.9735 - val_loss: 2.0890 - val_accuracy: 0.6980 Epoch 3/30 63/63 [==============================] - 68s 1s/step - loss: 0.0838 - accuracy: 0.9685 - val_loss: 1.4424 - val_accuracy: 0.7220 Epoch 4/30 63/63 [==============================] - 65s 1s/step - loss: 0.0570 - accuracy: 0.9840 - val_loss: 1.3466 - val_accuracy: 0.7440 Epoch 5/30 63/63 [==============================] - 76s 1s/step - loss: 0.0490 - accuracy: 0.9860 - val_loss: 1.2987 - val_accuracy: 0.7520 Epoch 6/30 63/63 [==============================] - 69s 1s/step - loss: 0.0692 - accuracy: 0.9765 - val_loss: 1.5693 - val_accuracy: 0.7560 Epoch 7/30 63/63 [==============================] - 65s 1s/step - loss: 0.0557 - accuracy: 0.9850 - val_loss: 1.5124 - val_accuracy: 0.7330 Epoch 8/30 63/63 [==============================] - 73s 1s/step - loss: 0.0456 - accuracy: 0.9850 - val_loss: 1.5896 - val_accuracy: 0.7310 Epoch 9/30 63/63 [==============================] - 59s 940ms/step - loss: 0.0362 - accuracy: 0.9875 - val_loss: 1.6021 - val_accuracy: 0.7410 Epoch 10/30 63/63 [==============================] - 58s 924ms/step - loss: 0.0309 - accuracy: 0.9905 - val_loss: 1.7103 - val_accuracy: 0.7440 Epoch 11/30 63/63 [==============================] - 60s 945ms/step - loss: 0.0388 - accuracy: 0.9905 - val_loss: 1.8422 - val_accuracy: 0.7460 Epoch 12/30 63/63 [==============================] - 59s 934ms/step - loss: 0.0667 - accuracy: 0.9810 - val_loss: 1.9422 - val_accuracy: 0.7300 Epoch 13/30 63/63 [==============================] - 62s 983ms/step - loss: 0.0267 - accuracy: 0.9925 - val_loss: 2.2143 - val_accuracy: 0.7340 Epoch 14/30 63/63 [==============================] - 74s 1s/step - loss: 0.0526 - accuracy: 0.9880 - val_loss: 2.1930 - val_accuracy: 0.7210 Epoch 15/30 63/63 [==============================] - 60s 945ms/step - loss: 0.0733 - accuracy: 0.9925 - val_loss: 2.5046 - val_accuracy: 0.6970 Epoch 16/30 63/63 [==============================] - 59s 936ms/step - loss: 0.0338 - accuracy: 0.9920 - val_loss: 2.2210 - val_accuracy: 0.7320 Epoch 17/30 63/63 [==============================] - 59s 940ms/step - loss: 0.0572 - accuracy: 0.9875 - val_loss: 2.9198 - val_accuracy: 0.7080 Epoch 18/30 63/63 [==============================] - 59s 937ms/step - loss: 0.0293 - accuracy: 0.9910 - val_loss: 2.6978 - val_accuracy: 0.7210 Epoch 19/30 63/63 [==============================] - 58s 916ms/step - loss: 0.0617 - accuracy: 0.9840 - val_loss: 2.6348 - val_accuracy: 0.7260 Epoch 20/30 63/63 [==============================] - 57s 911ms/step - loss: 0.0317 - accuracy: 0.9880 - val_loss: 2.7319 - val_accuracy: 0.7290 Epoch 21/30 63/63 [==============================] - 60s 950ms/step - loss: 0.0696 - accuracy: 0.9860 - val_loss: 2.8590 - val_accuracy: 0.7290 Epoch 22/30 63/63 [==============================] - 59s 941ms/step - loss: 0.0727 - accuracy: 0.9850 - val_loss: 2.5008 - val_accuracy: 0.7130 Epoch 23/30 63/63 [==============================] - 58s 914ms/step - loss: 0.0436 - accuracy: 0.9890 - val_loss: 2.6383 - val_accuracy: 0.7410 Epoch 24/30 63/63 [==============================] - 60s 944ms/step - loss: 0.0434 - accuracy: 0.9890 - val_loss: 2.6467 - val_accuracy: 0.7350 Epoch 25/30 63/63 [==============================] - 60s 944ms/step - loss: 0.0273 - accuracy: 0.9915 - val_loss: 2.9419 - val_accuracy: 0.7270 Epoch 26/30 63/63 [==============================] - 59s 939ms/step - loss: 0.0452 - accuracy: 0.9920 - val_loss: 2.6423 - val_accuracy: 0.7260 Epoch 27/30 63/63 [==============================] - 60s 954ms/step - loss: 0.0458 - accuracy: 0.9885 - val_loss: 2.5687 - val_accuracy: 0.7290 Epoch 28/30 63/63 [==============================] - 60s 945ms/step - loss: 0.0108 - accuracy: 0.9960 - val_loss: 3.2115 - val_accuracy: 0.7340 Epoch 29/30 63/63 [==============================] - 58s 921ms/step - loss: 0.0390 - accuracy: 0.9890 - val_loss: 2.9265 - val_accuracy: 0.7320 Epoch 30/30 63/63 [==============================] - 58s 922ms/step - loss: 0.0279 - accuracy: 0.9905 - val_loss: 3.3471 - val_accuracy: 0.7200
accuracy = history_1.history["accuracy"]
val_accuracy = history_1.history["val_accuracy"]
loss = history_1.history["loss"]
val_loss = history_1.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()
test_model_1 = keras.models.load_model(
"best_model_model1.hdf5")
test_loss_1, test_acc_1 = test_model_1.evaluate(test_dataset)
print(f"Test accuracy: {test_acc_1:.3f}")
63/63 [==============================] - 12s 182ms/step - loss: 1.1131 - accuracy: 0.7290 Test accuracy: 0.729
history_1_dict = history_1.history
hist_df_1 = pd.DataFrame(history_1_dict)
hist_df_1
| loss | accuracy | val_loss | val_accuracy | |
|---|---|---|---|---|
| 0 | 0.108392 | 0.9665 | 1.186704 | 0.734 |
| 1 | 0.071110 | 0.9735 | 2.088961 | 0.698 |
| 2 | 0.083778 | 0.9685 | 1.442383 | 0.722 |
| 3 | 0.056978 | 0.9840 | 1.346597 | 0.744 |
| 4 | 0.048969 | 0.9860 | 1.298726 | 0.752 |
| 5 | 0.069178 | 0.9765 | 1.569296 | 0.756 |
| 6 | 0.055669 | 0.9850 | 1.512403 | 0.733 |
| 7 | 0.045553 | 0.9850 | 1.589638 | 0.731 |
| 8 | 0.036161 | 0.9875 | 1.602066 | 0.741 |
| 9 | 0.030858 | 0.9905 | 1.710316 | 0.744 |
| 10 | 0.038763 | 0.9905 | 1.842248 | 0.746 |
| 11 | 0.066738 | 0.9810 | 1.942221 | 0.730 |
| 12 | 0.026669 | 0.9925 | 2.214325 | 0.734 |
| 13 | 0.052570 | 0.9880 | 2.192991 | 0.721 |
| 14 | 0.073299 | 0.9925 | 2.504561 | 0.697 |
| 15 | 0.033810 | 0.9920 | 2.221050 | 0.732 |
| 16 | 0.057207 | 0.9875 | 2.919831 | 0.708 |
| 17 | 0.029309 | 0.9910 | 2.697770 | 0.721 |
| 18 | 0.061717 | 0.9840 | 2.634845 | 0.726 |
| 19 | 0.031745 | 0.9880 | 2.731930 | 0.729 |
| 20 | 0.069556 | 0.9860 | 2.858980 | 0.729 |
| 21 | 0.072734 | 0.9850 | 2.500825 | 0.713 |
| 22 | 0.043605 | 0.9890 | 2.638330 | 0.741 |
| 23 | 0.043441 | 0.9890 | 2.646658 | 0.735 |
| 24 | 0.027320 | 0.9915 | 2.941912 | 0.727 |
| 25 | 0.045223 | 0.9920 | 2.642344 | 0.726 |
| 26 | 0.045754 | 0.9885 | 2.568705 | 0.729 |
| 27 | 0.010794 | 0.9960 | 3.211460 | 0.734 |
| 28 | 0.038990 | 0.9890 | 2.926472 | 0.732 |
| 29 | 0.027892 | 0.9905 | 3.347083 | 0.720 |
Training & Validation loss
Accuracy
Weights
conv_base = keras.applications.vgg16.VGG16(
weights="imagenet",
include_top=False,
input_shape=(180, 180, 3))
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5 58889256/58889256 [==============================] - 11s 0us/step
conv_base.summary()
Model: "vgg16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) [(None, 180, 180, 3)] 0
block1_conv1 (Conv2D) (None, 180, 180, 64) 1792
block1_conv2 (Conv2D) (None, 180, 180, 64) 36928
block1_pool (MaxPooling2D) (None, 90, 90, 64) 0
block2_conv1 (Conv2D) (None, 90, 90, 128) 73856
block2_conv2 (Conv2D) (None, 90, 90, 128) 147584
block2_pool (MaxPooling2D) (None, 45, 45, 128) 0
block3_conv1 (Conv2D) (None, 45, 45, 256) 295168
block3_conv2 (Conv2D) (None, 45, 45, 256) 590080
block3_conv3 (Conv2D) (None, 45, 45, 256) 590080
block3_pool (MaxPooling2D) (None, 22, 22, 256) 0
block4_conv1 (Conv2D) (None, 22, 22, 512) 1180160
block4_conv2 (Conv2D) (None, 22, 22, 512) 2359808
block4_conv3 (Conv2D) (None, 22, 22, 512) 2359808
block4_pool (MaxPooling2D) (None, 11, 11, 512) 0
block5_conv1 (Conv2D) (None, 11, 11, 512) 2359808
block5_conv2 (Conv2D) (None, 11, 11, 512) 2359808
block5_conv3 (Conv2D) (None, 11, 11, 512) 2359808
block5_pool (MaxPooling2D) (None, 5, 5, 512) 0
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________
import numpy as np
def get_features_and_labels(dataset):
all_features = []
all_labels = []
for images, labels in dataset:
preprocessed_images = keras.applications.vgg16.preprocess_input(images)
features = conv_base.predict(preprocessed_images)
all_features.append(features)
all_labels.append(labels)
return np.concatenate(all_features), np.concatenate(all_labels)
train_features, train_labels = get_features_and_labels(train_dataset)
val_features, val_labels = get_features_and_labels(validation_dataset)
test_features, test_labels = get_features_and_labels(test_dataset)
1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 1s 608ms/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 4s 4s/step 1/1 [==============================] - 2s 2s/step 1/1 [==============================] - 3s 3s/step 1/1 [==============================] - 1s 1s/step
conv_base.trainable = False
conv_base.summary(
)
Model: "vgg16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) [(None, 180, 180, 3)] 0
block1_conv1 (Conv2D) (None, 180, 180, 64) 1792
block1_conv2 (Conv2D) (None, 180, 180, 64) 36928
block1_pool (MaxPooling2D) (None, 90, 90, 64) 0
block2_conv1 (Conv2D) (None, 90, 90, 128) 73856
block2_conv2 (Conv2D) (None, 90, 90, 128) 147584
block2_pool (MaxPooling2D) (None, 45, 45, 128) 0
block3_conv1 (Conv2D) (None, 45, 45, 256) 295168
block3_conv2 (Conv2D) (None, 45, 45, 256) 590080
block3_conv3 (Conv2D) (None, 45, 45, 256) 590080
block3_pool (MaxPooling2D) (None, 22, 22, 256) 0
block4_conv1 (Conv2D) (None, 22, 22, 512) 1180160
block4_conv2 (Conv2D) (None, 22, 22, 512) 2359808
block4_conv3 (Conv2D) (None, 22, 22, 512) 2359808
block4_pool (MaxPooling2D) (None, 11, 11, 512) 0
block5_conv1 (Conv2D) (None, 11, 11, 512) 2359808
block5_conv2 (Conv2D) (None, 11, 11, 512) 2359808
block5_conv3 (Conv2D) (None, 11, 11, 512) 2359808
block5_pool (MaxPooling2D) (None, 5, 5, 512) 0
=================================================================
Total params: 14,714,688
Trainable params: 0
Non-trainable params: 14,714,688
_________________________________________________________________
data_augmentation = keras.Sequential(
[
layers.RandomFlip("horizontal"),
layers.RandomRotation(0.1),
layers.RandomZoom(0.2),
]
)
inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = keras.applications.vgg16.preprocess_input(x)
x = conv_base(x)
x = layers.Flatten()(x)
x = layers.Dense(256)(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model_2 = keras.Model(inputs, outputs)
model_2.summary()
Model: "model_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_4 (InputLayer) [(None, 180, 180, 3)] 0
sequential_1 (Sequential) (None, 180, 180, 3) 0
tf.__operators__.getitem_1 (None, 180, 180, 3) 0
(SlicingOpLambda)
tf.nn.bias_add_1 (TFOpLambd (None, 180, 180, 3) 0
a)
vgg16 (Functional) (None, 5, 5, 512) 14714688
flatten_2 (Flatten) (None, 12800) 0
dense_3 (Dense) (None, 256) 3277056
dropout_1 (Dropout) (None, 256) 0
dense_4 (Dense) (None, 1) 257
=================================================================
Total params: 17,992,001
Trainable params: 3,277,313
Non-trainable params: 14,714,688
_________________________________________________________________
model_2.compile(loss="binary_crossentropy",
optimizer="rmsprop",
metrics=["accuracy"])
checkpoint_filepath = 'best_model.hdf5'
callbacks = [
keras.callbacks.ModelCheckpoint(
filepath=checkpoint_filepath,
save_best_only=True,
monitor="val_loss",
mode='min')]
history_2 = model_2.fit(
train_dataset,
epochs=50,
validation_data=validation_dataset,
callbacks=callbacks)
Epoch 1/50 63/63 [==============================] - 255s 4s/step - loss: 18.5507 - accuracy: 0.8995 - val_loss: 6.2611 - val_accuracy: 0.9570 Epoch 2/50 63/63 [==============================] - 242s 4s/step - loss: 6.5969 - accuracy: 0.9430 - val_loss: 5.9659 - val_accuracy: 0.9680 Epoch 3/50 63/63 [==============================] - 273s 4s/step - loss: 5.4062 - accuracy: 0.9565 - val_loss: 3.3580 - val_accuracy: 0.9790 Epoch 4/50 63/63 [==============================] - 231s 4s/step - loss: 4.3760 - accuracy: 0.9645 - val_loss: 5.3678 - val_accuracy: 0.9700 Epoch 5/50 63/63 [==============================] - 216s 3s/step - loss: 3.4563 - accuracy: 0.9675 - val_loss: 3.8726 - val_accuracy: 0.9720 Epoch 6/50 63/63 [==============================] - 237s 4s/step - loss: 4.8383 - accuracy: 0.9610 - val_loss: 4.1494 - val_accuracy: 0.9790 Epoch 7/50 63/63 [==============================] - 277s 4s/step - loss: 3.2910 - accuracy: 0.9675 - val_loss: 3.3694 - val_accuracy: 0.9770 Epoch 8/50 63/63 [==============================] - 294s 5s/step - loss: 3.2692 - accuracy: 0.9685 - val_loss: 3.5386 - val_accuracy: 0.9760 Epoch 9/50 63/63 [==============================] - 291s 5s/step - loss: 2.0611 - accuracy: 0.9765 - val_loss: 2.7030 - val_accuracy: 0.9830 Epoch 10/50 63/63 [==============================] - 292s 5s/step - loss: 2.5690 - accuracy: 0.9740 - val_loss: 2.2225 - val_accuracy: 0.9840 Epoch 11/50 63/63 [==============================] - 292s 5s/step - loss: 2.2632 - accuracy: 0.9710 - val_loss: 2.2174 - val_accuracy: 0.9830 Epoch 12/50 63/63 [==============================] - 289s 5s/step - loss: 2.3296 - accuracy: 0.9745 - val_loss: 2.2874 - val_accuracy: 0.9800 Epoch 13/50 63/63 [==============================] - 290s 5s/step - loss: 1.3403 - accuracy: 0.9855 - val_loss: 2.3212 - val_accuracy: 0.9790 Epoch 14/50 63/63 [==============================] - 290s 5s/step - loss: 2.2995 - accuracy: 0.9775 - val_loss: 2.5218 - val_accuracy: 0.9780 Epoch 15/50 63/63 [==============================] - 291s 5s/step - loss: 2.0498 - accuracy: 0.9740 - val_loss: 2.1650 - val_accuracy: 0.9790 Epoch 16/50 63/63 [==============================] - 307s 5s/step - loss: 1.0529 - accuracy: 0.9815 - val_loss: 1.9175 - val_accuracy: 0.9780 Epoch 17/50 63/63 [==============================] - 293s 5s/step - loss: 1.8027 - accuracy: 0.9755 - val_loss: 5.1194 - val_accuracy: 0.9670 Epoch 18/50 63/63 [==============================] - 290s 5s/step - loss: 1.2299 - accuracy: 0.9810 - val_loss: 1.5622 - val_accuracy: 0.9830 Epoch 19/50 63/63 [==============================] - 290s 5s/step - loss: 0.7268 - accuracy: 0.9855 - val_loss: 2.3659 - val_accuracy: 0.9760 Epoch 20/50 63/63 [==============================] - 291s 5s/step - loss: 0.8653 - accuracy: 0.9865 - val_loss: 2.3768 - val_accuracy: 0.9800 Epoch 21/50 63/63 [==============================] - 290s 5s/step - loss: 1.3966 - accuracy: 0.9785 - val_loss: 1.7610 - val_accuracy: 0.9790 Epoch 22/50 63/63 [==============================] - 289s 5s/step - loss: 1.0984 - accuracy: 0.9825 - val_loss: 2.4212 - val_accuracy: 0.9770 Epoch 23/50 63/63 [==============================] - 290s 5s/step - loss: 0.9518 - accuracy: 0.9815 - val_loss: 2.0234 - val_accuracy: 0.9790 Epoch 24/50 63/63 [==============================] - 289s 5s/step - loss: 0.8975 - accuracy: 0.9865 - val_loss: 2.0105 - val_accuracy: 0.9780 Epoch 25/50 63/63 [==============================] - 289s 5s/step - loss: 0.6552 - accuracy: 0.9885 - val_loss: 2.1820 - val_accuracy: 0.9760 Epoch 26/50 63/63 [==============================] - 289s 5s/step - loss: 0.4651 - accuracy: 0.9880 - val_loss: 2.1535 - val_accuracy: 0.9780 Epoch 27/50 63/63 [==============================] - 290s 5s/step - loss: 0.7569 - accuracy: 0.9865 - val_loss: 2.0905 - val_accuracy: 0.9800 Epoch 28/50 63/63 [==============================] - 286s 5s/step - loss: 0.9833 - accuracy: 0.9825 - val_loss: 2.2268 - val_accuracy: 0.9800 Epoch 29/50 63/63 [==============================] - 288s 5s/step - loss: 0.7433 - accuracy: 0.9860 - val_loss: 2.7026 - val_accuracy: 0.9770 Epoch 30/50 63/63 [==============================] - 293s 5s/step - loss: 0.9471 - accuracy: 0.9830 - val_loss: 2.0925 - val_accuracy: 0.9790 Epoch 31/50 63/63 [==============================] - 289s 5s/step - loss: 0.3297 - accuracy: 0.9945 - val_loss: 2.3164 - val_accuracy: 0.9770 Epoch 32/50 63/63 [==============================] - 286s 5s/step - loss: 1.0803 - accuracy: 0.9830 - val_loss: 2.1292 - val_accuracy: 0.9830 Epoch 33/50 63/63 [==============================] - 289s 5s/step - loss: 0.7320 - accuracy: 0.9855 - val_loss: 2.0574 - val_accuracy: 0.9790 Epoch 34/50 63/63 [==============================] - 287s 5s/step - loss: 0.4860 - accuracy: 0.9910 - val_loss: 1.8950 - val_accuracy: 0.9820 Epoch 35/50 63/63 [==============================] - 288s 5s/step - loss: 0.6043 - accuracy: 0.9885 - val_loss: 1.8690 - val_accuracy: 0.9830 Epoch 36/50 63/63 [==============================] - 287s 5s/step - loss: 0.6052 - accuracy: 0.9870 - val_loss: 1.6292 - val_accuracy: 0.9810 Epoch 37/50 63/63 [==============================] - 288s 5s/step - loss: 0.9456 - accuracy: 0.9830 - val_loss: 1.8927 - val_accuracy: 0.9800 Epoch 38/50 63/63 [==============================] - 288s 5s/step - loss: 0.5197 - accuracy: 0.9855 - val_loss: 1.6955 - val_accuracy: 0.9820 Epoch 39/50 63/63 [==============================] - 289s 5s/step - loss: 0.6802 - accuracy: 0.9845 - val_loss: 2.3554 - val_accuracy: 0.9810 Epoch 40/50 63/63 [==============================] - 291s 5s/step - loss: 0.7947 - accuracy: 0.9845 - val_loss: 2.0510 - val_accuracy: 0.9790 Epoch 41/50 63/63 [==============================] - 290s 5s/step - loss: 0.6071 - accuracy: 0.9880 - val_loss: 1.8148 - val_accuracy: 0.9790 Epoch 42/50 63/63 [==============================] - 291s 5s/step - loss: 0.4787 - accuracy: 0.9890 - val_loss: 4.8375 - val_accuracy: 0.9620 Epoch 43/50 63/63 [==============================] - 293s 5s/step - loss: 0.8638 - accuracy: 0.9835 - val_loss: 2.2905 - val_accuracy: 0.9770 Epoch 44/50 63/63 [==============================] - 294s 5s/step - loss: 0.4971 - accuracy: 0.9880 - val_loss: 3.5240 - val_accuracy: 0.9690 Epoch 45/50 63/63 [==============================] - 288s 5s/step - loss: 0.4974 - accuracy: 0.9890 - val_loss: 1.7036 - val_accuracy: 0.9800 Epoch 46/50 63/63 [==============================] - 288s 5s/step - loss: 0.2960 - accuracy: 0.9910 - val_loss: 2.5766 - val_accuracy: 0.9770 Epoch 47/50 63/63 [==============================] - 287s 5s/step - loss: 0.3670 - accuracy: 0.9920 - val_loss: 2.9472 - val_accuracy: 0.9760 Epoch 48/50 63/63 [==============================] - 288s 5s/step - loss: 0.3266 - accuracy: 0.9910 - val_loss: 1.8827 - val_accuracy: 0.9780 Epoch 49/50 63/63 [==============================] - 286s 5s/step - loss: 0.6584 - accuracy: 0.9890 - val_loss: 2.1387 - val_accuracy: 0.9780 Epoch 50/50 63/63 [==============================] - 288s 5s/step - loss: 0.4668 - accuracy: 0.9900 - val_loss: 1.6586 - val_accuracy: 0.9800
acc = history_2.history["accuracy"]
val_acc = history_2.history["val_accuracy"]
loss = history_2.history["loss"]
val_loss = history_2.history["val_loss"]
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, "bo", label="Training accuracy")
plt.plot(epochs, val_acc, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()
test_model_2 = keras.models.load_model(
"best_model.hdf5")
test_loss_2, test_acc_2 = test_model_2.evaluate(test_dataset)
print(f"Test accuracy: {test_acc_2:.3f}")
63/63 [==============================] - 194s 3s/step - loss: 2.4849 - accuracy: 0.9765 Test accuracy: 0.976
history_2_dict = history_2.history
hist_df_2 = pd.DataFrame(history_2_dict)
hist_df_2
| loss | accuracy | val_loss | val_accuracy | |
|---|---|---|---|---|
| 0 | 18.550718 | 0.8995 | 6.261053 | 0.957 |
| 1 | 6.596909 | 0.9430 | 5.965850 | 0.968 |
| 2 | 5.406242 | 0.9565 | 3.357971 | 0.979 |
| 3 | 4.376008 | 0.9645 | 5.367783 | 0.970 |
| 4 | 3.456275 | 0.9675 | 3.872593 | 0.972 |
| 5 | 4.838308 | 0.9610 | 4.149443 | 0.979 |
| 6 | 3.291010 | 0.9675 | 3.369395 | 0.977 |
| 7 | 3.269237 | 0.9685 | 3.538553 | 0.976 |
| 8 | 2.061107 | 0.9765 | 2.702962 | 0.983 |
| 9 | 2.568978 | 0.9740 | 2.222455 | 0.984 |
| 10 | 2.263160 | 0.9710 | 2.217408 | 0.983 |
| 11 | 2.329571 | 0.9745 | 2.287379 | 0.980 |
| 12 | 1.340334 | 0.9855 | 2.321165 | 0.979 |
| 13 | 2.299511 | 0.9775 | 2.521809 | 0.978 |
| 14 | 2.049802 | 0.9740 | 2.165018 | 0.979 |
| 15 | 1.052905 | 0.9815 | 1.917543 | 0.978 |
| 16 | 1.802688 | 0.9755 | 5.119412 | 0.967 |
| 17 | 1.229874 | 0.9810 | 1.562165 | 0.983 |
| 18 | 0.726829 | 0.9855 | 2.365862 | 0.976 |
| 19 | 0.865333 | 0.9865 | 2.376798 | 0.980 |
| 20 | 1.396641 | 0.9785 | 1.760978 | 0.979 |
| 21 | 1.098444 | 0.9825 | 2.421160 | 0.977 |
| 22 | 0.951769 | 0.9815 | 2.023438 | 0.979 |
| 23 | 0.897475 | 0.9865 | 2.010543 | 0.978 |
| 24 | 0.655156 | 0.9885 | 2.181980 | 0.976 |
| 25 | 0.465060 | 0.9880 | 2.153502 | 0.978 |
| 26 | 0.756925 | 0.9865 | 2.090546 | 0.980 |
| 27 | 0.983262 | 0.9825 | 2.226842 | 0.980 |
| 28 | 0.743338 | 0.9860 | 2.702588 | 0.977 |
| 29 | 0.947119 | 0.9830 | 2.092499 | 0.979 |
| 30 | 0.329667 | 0.9945 | 2.316390 | 0.977 |
| 31 | 1.080271 | 0.9830 | 2.129171 | 0.983 |
| 32 | 0.731980 | 0.9855 | 2.057376 | 0.979 |
| 33 | 0.485960 | 0.9910 | 1.895024 | 0.982 |
| 34 | 0.604330 | 0.9885 | 1.869005 | 0.983 |
| 35 | 0.605171 | 0.9870 | 1.629161 | 0.981 |
| 36 | 0.945603 | 0.9830 | 1.892708 | 0.980 |
| 37 | 0.519740 | 0.9855 | 1.695460 | 0.982 |
| 38 | 0.680225 | 0.9845 | 2.355415 | 0.981 |
| 39 | 0.794716 | 0.9845 | 2.050990 | 0.979 |
| 40 | 0.607126 | 0.9880 | 1.814754 | 0.979 |
| 41 | 0.478695 | 0.9890 | 4.837509 | 0.962 |
| 42 | 0.863818 | 0.9835 | 2.290490 | 0.977 |
| 43 | 0.497062 | 0.9880 | 3.523992 | 0.969 |
| 44 | 0.497401 | 0.9890 | 1.703560 | 0.980 |
| 45 | 0.296035 | 0.9910 | 2.576616 | 0.977 |
| 46 | 0.367049 | 0.9920 | 2.947249 | 0.976 |
| 47 | 0.326603 | 0.9910 | 1.882694 | 0.978 |
| 48 | 0.658422 | 0.9890 | 2.138710 | 0.978 |
| 49 | 0.466835 | 0.9900 | 1.658611 | 0.980 |
Training & Validation loss
Accuracy
Weights
Summarised Conclusion is give below
| Model Name | Highest Val Accuracy | Val_Loss | Epoch | |
|---|---|---|---|---|
| Model_1 | 0.752 | 1.298726 | 4 | |
| Model_2 Fine Tuning | 0.981 | 1.629161 | 35 |
Accuracy for test set | Model Name | Accuracy | |------------|----------------------| | Model_1 | 0.729 | | Model_2 Fine Tuning | 0.976|
I am using ImageDatagenerator in this step to get lables and features for validation dataset.
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.models import load_model
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, precision_recall_curve
import matplotlib.pyplot as plt
validation_dir = 'datacats_and_dogs_small/validation'
img_height, img_width = 180, 180
batch_size = 32
validation_image_generator = ImageDataGenerator(rescale=1./255)
val_data_gen = validation_image_generator.flow_from_directory(
validation_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='binary')
Found 1000 images belonging to 2 classes.
Accuracy
# Load the best model
model1_new = load_model('best_model_model1.hdf5')
y_pred_model1 = model1_new.predict(val_data_gen)
y_pred_class_model1 = np.round(y_pred_model1).astype(int)
validation_labels = val_data_gen.classes
accuracy_model1 = accuracy_score(validation_labels, y_pred_class_model1)
print("Accuracy - Model 1:", accuracy_model1)
32/32 [==============================] - 12s 385ms/step Accuracy - Model 1: 0.5
Confusion Matrix
# Confusion matrix
conf_matrix_model1 = confusion_matrix(validation_labels, y_pred_class_model1)
sns.heatmap(conf_matrix_model1, annot=True, fmt='d', cmap='Blues')
<Axes: >
Precision, Recall, F1-Score
# Generate classification report
report = classification_report(validation_labels, y_pred_class_model1, output_dict=True)
# Convert report to pandas DataFrame
report_df = pd.DataFrame(report).transpose()
# Display the report
display(report_df)
| precision | recall | f1-score | support | |
|---|---|---|---|---|
| 0 | 0.50 | 1.0 | 0.666667 | 500.0 |
| 1 | 0.00 | 0.0 | 0.000000 | 500.0 |
| accuracy | 0.50 | 0.5 | 0.500000 | 0.5 |
| macro avg | 0.25 | 0.5 | 0.333333 | 1000.0 |
| weighted avg | 0.25 | 0.5 | 0.333333 | 1000.0 |
Precision-Recall Curve
# Precision-Recall curve
precision_model1, recall_model1, _ = precision_recall_curve(validation_labels, y_pred_model1)
plt.plot(recall_model1, precision_model1, label='Model 1')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.legend()
plt.show()
Accuracy
# Load the best model
model2_new = load_model('best_model.hdf5')
y_pred_model2 = model2_new.predict(val_data_gen)
y_pred_class_model2 = np.round(y_pred_model2).astype(int)
accuracy_model2 = accuracy_score(validation_labels, y_pred_class_model2)
print("Accuracy - Model 2:", accuracy_model2)
63/63 [==============================] - 209s 3s/step Accuracy - Model 2: 0.5
Confusion matrix
# Confusion matrix
conf_matrix_model2 = confusion_matrix(validation_labels, y_pred_class_model2)
sns.heatmap(conf_matrix_model2, annot=True, fmt='d', cmap='Blues')
<Axes: >
# Generate classification report
report_2 = classification_report(validation_labels, y_pred_class_model2, output_dict=True)
# Convert report to pandas DataFrame
report_df_2 = pd.DataFrame(report_2).transpose()
# Display the report
display(report_df_2)
| precision | recall | f1-score | support | |
|---|---|---|---|---|
| 0 | 0.50 | 1.0 | 0.666667 | 500.0 |
| 1 | 0.00 | 0.0 | 0.000000 | 500.0 |
| accuracy | 0.50 | 0.5 | 0.500000 | 0.5 |
| macro avg | 0.25 | 0.5 | 0.333333 | 1000.0 |
| weighted avg | 0.25 | 0.5 | 0.333333 | 1000.0 |
# Precision-Recall curve
precision_model2, recall_model2, _ = precision_recall_curve(validation_labels, y_pred_model2)
plt.plot(recall_model2, precision_model2, label='Model 2')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.legend()
plt.show()